<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">



	<title>setInterval(s, i) vs. setTimeout(s, i)</title>
	<style type="text/css" media="screen">
/* <![CDATA[ */

.abs {
	position: absolute;
	visibility: hidden;
	top: 0;
	left: 0;
}

#rocket {
	background: blue;
	border: 3px groove teal;
	height: 40px;
	width: 40px;
}

/* ]]> */
</style>
	<script type="text/javascript" defer="defer">
// <![CDATA[

function singleThread(id) {

	var ew = ElementWrapper.getInstance(id);
	
	if(ew.getLock()) { // should be synchronized.
		ew.css.visibility = "visible";
		var t0 = new Date().getTime();
		
		ew.ondonemoving = function() {
			this.moveToLeft0();
			ew.ondonemoving = function() {
				document.getElementById("monitor1").innerHTML = 
					("single threading took: "+ (new Date().getTime() - t0));
			};
		};
		ew.moveToRight600();
	}
		
}

function doubleThread(id) {
	var ew = ElementWrapper.getInstance(id);
	
	if(ew.getLock()) { // should be synchronized.
		ew.css.visibility = "visible";
		var t0 = new Date().getTime();
	
		ew.ondonemoving = function() {
			ew.moveToLeft0_DblThread();
			ew.ondonemoving = function() {
				document.getElementById("monitor2").innerHTML = 
				("double threading took: "+ (new Date().getTime() - t0));
			};
		};
		ew.moveToRight600_DblThread();
	}
		
}

ElementWrapper = function(el) {
	this.el = el;
	this.id = el.id;
	this.css = this.el.style; // shorten object chain.
	
 // use parseInt here once to avoid repeated calls in moveTo.
	this.x = parseInt(this.css.left) || 0; 
	this.y = parseInt(this.css.top) || 0;
	ElementWrappers[this.id] = this;
};

ElementWrappers = { };

ElementWrapper.getInstance = function(id) {
	var x = ElementWrappers[id];
	if(x == null)
		x = ElementWrappers[id] = new ElementWrapper(document.getElementById(id));
	return x;
};

ElementWrapper.prototype = {

	animTimer : 0,
	animTimer2 : 0,
	
	isBlocked : false,
/**
 * Moves the element to a pixel coordinate.
 * This works, but is not optimally efficient.
 */
	moveTo : function(x, y) {
	  // inlining assignment for faster performance.
		this.css.left = (this.x = x) + "px";
		this.css.top = (this.y = y) + "px";
	},
	moveBy : function(x, y) {
	  // inlining assignment for faster performance.
		this.css.left = (this.x += x) + "px";
		this.css.top = (this.y += y) + "px";
	},
	
	moveToRight600 : function() {	
		this.animTimer = setInterval("ElementWrappers."+this.id+".moveRight600()", 1);
	},
	moveToLeft0 : function() {	
		this.animTimer = setInterval("ElementWrappers."+this.id+".moveLeft0()", 1);
	},
	
	
	moveToRight600_DblThread : function() {
		this.animTimer = setInterval("ElementWrappers."+this.id+".moveRight600()", 1);
		this.animTimer2 = setInterval("ElementWrappers."+this.id+".moveRight600()", 1);
	},
	moveToLeft0_DblThread : function() {	

		this.animTimer = setInterval("ElementWrappers."+this.id+".moveLeft0()", 1);
		this.animTimer2 = setInterval("ElementWrappers."+this.id+".moveLeft0()", 1);
	},


	moveLeft0 : function() {
		if(this.x <= 0) {
			clearInterval(this.animTimer);
			clearInterval(this.animTimer2);
			this.releaseLock();
			this.ondonemoving();
		}
		this.moveBy(-2,0);
	},
	moveRight600 : function() {
		if(this.x >= 600) {
			clearInterval(this.animTimer);
			clearInterval(this.animTimer2);
			this.ondonemoving();
		}
		this.moveBy(2,0);
	},
		
	ondonemoving : function(){},
	
	getLock : function(){ 
		if(this.isBlocked) return false;
		return this.isBlocked = true;
	},
	
	releaseLock : function(){ this.isBlocked = false; }
};


// ]]>
</script>
</head><body>
	<div style="visibility: visible; left: -2px; top: 0px;" id="rocket" class="abs"></div>
	
<div style="position: absolute; top: 110px;">
	<h1>Single Threading VS. Double Threading</h1>
	<h2>Single Threading</h2>
		<div>
	<input onclick='singleThread("rocket")' value="singleThread(&quot;rocket&quot;)" type="button">
	<span id="monitor1">single threading took: 8091</span>
	</div>
		<div>
	<h2>Double Threading</h2>
	<input onclick='doubleThread("rocket")' value="doubleThread(&quot;rocket&quot;)" type="button">
	<span id="monitor2">double threading took: 6160</span>
	</div>
	
	<hr>
	<p>
	Although double threading is roughly twice as fast, the animation 
	will become jerky in some browsers (such as Mozilla).
	</p>
	<p>
		This technique is best reserved for Internet Explorer running on Win9x.
	</p>
</div>
</body></html>